home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / strategy / xpat2-1.000 / xpat2-1 / xpat2-1.04 / src / X-layout.c < prev    next >
C/C++ Source or Header  |  1995-01-29  |  22KB  |  776 lines

  1. /*****************************************************************************/
  2. /*                                         */
  3. /*                                         */
  4. /*    X patience version 2 -- module X-layout.c                 */
  5. /*                                         */
  6. /*    Layout function for the X interface                     */
  7. /*    written by Heiko Eissfeldt and Michael Bischoff                 */
  8. /*    see COPYRIGHT.xpat2 for Copyright details                 */
  9. /*                                         */
  10. /*                                         */
  11. /*****************************************************************************/
  12. #include "X-pat.h"
  13.  
  14. /* layout types for Spider, Gypsy are 0..7 */
  15. #define FREECELL_MAGIC        0x220
  16. #define DELIGHT_MAGIC        0x260
  17. #define MONTECARLO_MAGIC    0x320
  18. #define MIDNIGHTOIL_MAGIC    0x370
  19. #define MICHAELS_MAGIC        0x3c0
  20. #define ROYAL_MAGIC        0x3e0
  21. #define BAKERS_MAGIC        0x400
  22. #define CANFIELD_MAGIC        0x420
  23.  
  24. #define MCDX 14
  25. #define MCDY 4
  26.  
  27. /* how far may slots at the bottom of the window be extended? */
  28. /* I think it sufffices if 1/3 of the card is visible */
  29. #define BOTTOM_INC    (graphic.ygap + 2*CARD_HEIGHT/3)
  30.  
  31. void new_rules_notify(void) {
  32.     XSize_t w, h;
  33. #ifdef useXview
  34.     xv_set(mainwindow,
  35.        FRAME_LABEL, (rules.longname? rules.longname: rules.shortname),
  36.        0);
  37. #else
  38.     XStoreName(dpy, mainwindow, rules.longname ? rules.longname : rules.shortname);
  39. #endif
  40.     refresh_screen();        /* sometimes needed (at least if area is smaller) */
  41.     
  42.     /* compute minimum size */
  43.     generic_minwindow(&w, &h);
  44.     graphic.min_width = w;
  45.     graphic.min_height = h;
  46. #ifdef LABER
  47.     printf("min size set to %d, %d\n", w, h);
  48. #endif
  49. #ifdef useXlib
  50.     {   XSizeHints xsh;
  51.     xsh.flags = PMinSize;
  52.     xsh.min_width = w;
  53.     xsh.min_height = h;
  54.     XSetWMNormalHints(dpy, table, &xsh);
  55.     }
  56.     w = max(graphic.width, w);
  57.     h = max(graphic.height, h);
  58. #else
  59.     w = max(w, graphic.w_width);
  60.     h = max(h, graphic.w_height);
  61. #endif
  62.     /* w and h are the maximum of the current visible size and the minimum size */
  63.     if (w != graphic.width || h != graphic.height)
  64.     soft_Resize(w, h);        /* request a resize if greater */
  65.     init_layout();            /* new setup */
  66. }
  67.  
  68. void cmd_Layout(void) {
  69.     int i;
  70.     init_layout();
  71.     for (i = FIRST_SLOT; i <= LAST_SLOT; ++i)
  72.     if (pile_resize(i))
  73.         draw_pileupdate(i, 0);
  74. }
  75.  
  76.  
  77. #ifndef useXlib
  78.  
  79. #define calc_yoff(w)    graphic.ygap
  80. #define YOFF        graphic.ygap
  81.  
  82. #else    /* Xlib must do some work */
  83.  
  84. #define YOFF        graphic.yoff
  85.  
  86. int arrange_buttons(struct singlebutton *b, int *startx, int *starty,
  87.     XSize_t maxx, long *magic) {
  88.     int x, y, num;
  89.     long mask;
  90.     /* printf("arrange width %d\n", maxx); */
  91.     x = *startx;
  92.     y = *starty;
  93.     num = 0;
  94.     *magic = 0;
  95.     mask = 1L;
  96.     while (b->text) {        /* weiterer button vorhanden */
  97.     ++num;
  98.     b->x = x;
  99.     b->y = y;
  100.     b->w = 2 * button.bx + XTextWidth(button.font, b->text, strlen(b->text));
  101.     b->h = 2 * button.by + button.fontheight;
  102.  
  103.     while (x > graphic.xgap && x + b->w + graphic.xgap >= maxx) {
  104.         /* line is full, next line */
  105.         *magic |= mask;
  106.         x = *startx;
  107.         y += 2 * button.by + button.fontheight + graphic.ygap;
  108.         b->x = x;
  109.         b->y = y;
  110.     }
  111.     mask <<= 1;
  112.     x += b->w + graphic.xgap;
  113.     ++b;
  114.     }
  115.     *startx = x;
  116.     *starty = y + 2 * button.by + button.fontheight + graphic.ygap;
  117.     return num;
  118. }
  119.  
  120. static int calc_yoff(int w) {
  121.     long dummy;
  122.     int x, y;
  123.     x = graphic.xgap;
  124.     y = graphic.ygap;
  125.     button.num = arrange_buttons(button.b, &x, &y, w, &dummy);
  126.     graphic.buttons_height = y;
  127.     graphic.message_x = 10;
  128.     graphic.message_y = y + TABLE_BW + graphic.message_font->ascent;
  129.     graphic.message_height = 2 * TABLE_BW +
  130.     graphic.message_font->ascent + graphic.message_font->descent;
  131.     return graphic.buttons_height + graphic.message_height + graphic.ygap;
  132. }
  133. #endif
  134.  
  135.  
  136.  
  137. /* there are 4 types of piles: VDECK, tmps, slots, stacks */
  138. /* the IDECK is of no interest for this function */
  139. #define SLOTFACTOR 2    /* minimum std height of a slot, measured in units
  140.                (CARD_HEIGHT+graphic.ygap) */
  141.  
  142. void generic_minwindow(XSize_t *x, XSize_t *y) {    
  143.     int min1;
  144.  
  145.     switch (rules.layout_hints) {
  146.     case 0:
  147.     if (!rules.numtmps) {
  148.        XSize_t x1, y1, x2, y2;
  149.     
  150.        if (rules.numstacks > rules.numslots)
  151.            min1 = rules.numstacks;
  152.        else if (rules.numstacks == rules.numslots)
  153.            min1 = rules.numstacks + (rules.variant & DECK_SOURCE ? 1 : 0);
  154.        else  /* stacks < slots */ if (rules.variant & DECK_SOURCE)
  155.            min1 = max(rules.numstacks+2, rules.numslots);
  156.        else
  157.            min1 = rules.numslots;
  158.        
  159.        x1 = graphic.xgap * (min1+1) + CARD_WIDTH * min1;
  160.        y1 = calc_yoff(x1) + (CARD_HEIGHT + graphic.ygap) * (SLOTFACTOR+1);
  161.        
  162.        min1 = rules.numslots + rules.numdecks;
  163.        if (rules.variant & DECK_SOURCE)
  164.            ++min1;
  165.        x2 = graphic.xgap * (min1+1) + CARD_WIDTH * min1;
  166.        y2 = calc_yoff(x2) + (CARD_HEIGHT + graphic.ygap) * 4;
  167.        
  168.        /* as a selection rule, minimize the size of the window needed */
  169.        if (x1 * y1 < x2 * y2) {    /* stacks on the top */
  170.            *x = x1;
  171.            *y = y1;
  172.        } else {    /* stacks on the right side */
  173.            *x = x2;
  174.            *y = y2;
  175.        }
  176.        return;
  177.     }
  178.     /* else fall thru to SeaHaven type */
  179.     case 1:
  180.     min1 = max(rules.numslots, rules.numstacks + rules.numtmps);
  181.     *x = graphic.xgap * (min1+1) + CARD_WIDTH * min1;
  182.     *y = calc_yoff(*x) + (CARD_HEIGHT + graphic.ygap) * (SLOTFACTOR+1);
  183.     return;
  184.     case 2:
  185.     /* The deck, the stack, the slots */
  186.     min1 = rules.numslots + 1;
  187.     *x = graphic.xgap * (min1+1) + CARD_WIDTH * min1;
  188.     *y = calc_yoff(*x) + (CARD_HEIGHT + graphic.ygap) * (SLOTFACTOR+1);
  189.     return;
  190.     case 3:    /* Monte Carlo */
  191.     /* The deck, no stack, the slots */
  192.     min1 = 1+rules.param[1];
  193.     *x = graphic.xgap - MCDX + min1 * (CARD_WIDTH + graphic.xgap + MCDX);
  194.     *y = calc_yoff(*x) + (CARD_HEIGHT + MCDY + graphic.ygap) * 
  195.         ((rules.numslots+rules.param[1]-1)/rules.param[1]);
  196.     return;
  197.     case 4:    /* Midnight Oil: 18 Slots */
  198.     /* The deck, no stack, the slots */
  199.     min1 = (rules.numslots/2) + rules.numdecks;
  200.     *x = graphic.xgap * (min1+1) + CARD_WIDTH * min1;
  201.     *y = calc_yoff(*x) + (CARD_HEIGHT + graphic.ygap) * 4;
  202.     return;
  203.     case 5:    /* Michael's Fantasy */
  204.     /* No deck, 4 stacks, 4 Tmps, the slots */
  205.     *x = 3 * graphic.xgap + (3 + rules.numslots) 
  206.         * (CARD_WIDTH + graphic.xgap);
  207.     *y = calc_yoff(*x) + (CARD_HEIGHT + graphic.ygap) * 3;
  208.     return;
  209.     case 6:    /* Royal Cotillion */
  210.     /* No deck, 4 stacks, 4 Tmps, the slots */
  211.     min1 = max(2, rules.numslots) + rules.numdecks + (rules.numtmps+3)/4;
  212.     *x = 3 * graphic.xgap + min1 * (CARD_WIDTH + graphic.xgap);
  213.     *y = calc_yoff(*x) + (CARD_HEIGHT + graphic.ygap) * 4;
  214.     return;
  215.     case 7:    /* Baker's Dozen */
  216.     /* No deck, 4 stacks, a dozen slots */
  217.     min1 = rules.numdecks + (rules.numslots+1)/2;
  218.     *x = graphic.xgap + min1 * (CARD_WIDTH + graphic.xgap);
  219.     *y = calc_yoff(*x) + (CARD_HEIGHT + graphic.ygap) * 4;
  220.     return;
  221.     case 8:    /* Canfield */
  222.     /* No deck, 4 stacks, a dozen slots */
  223.     *x = graphic.xgap + 5 * (CARD_WIDTH + graphic.xgap);
  224.     *y = calc_yoff(*x) + (CARD_HEIGHT + graphic.ygap) * 4;
  225.     return;
  226.     }
  227. }
  228.  
  229. static int FreeCell_layout(int xnum, int ynum, int h) {
  230.     int i, cols, off;
  231.     struct pile *p = graphic.pile;
  232.  
  233.     cols = max(rules.numslots, rules.numstacks + rules.numtmps);
  234.  
  235.     off = cols - rules.numstacks;
  236.     for (i = 0; i < rules.numstacks; ++i) {
  237.     p->x = graphic.xgap + (graphic.xgap + CARD_WIDTH) * (i+off);
  238.     p->y = YOFF;
  239.     p->xtotal = CARD_WIDTH;
  240.     p->ymaxheight = CARD_HEIGHT;
  241.     ++p;
  242.     }
  243.     off = cols - rules.numslots;
  244.     for (i = 0; i < rules.numslots; ++i) {
  245.     p->x = graphic.xgap + (graphic.xgap + CARD_WIDTH) * (i+off);
  246.     p->y = YOFF + graphic.ygap + CARD_HEIGHT;
  247.     p->xtotal = CARD_WIDTH;
  248.     p->ymaxheight = h - YOFF - CARD_HEIGHT - graphic.ygap + BOTTOM_INC;
  249.     ++p;
  250.     }
  251.     off = 0;
  252.     for (i = 0; i < rules.numtmps; ++i) {
  253.     p->x = graphic.xgap + (graphic.xgap + CARD_WIDTH) * (i+off);
  254.     p->y = YOFF;
  255.     p->xtotal = CARD_WIDTH;
  256.     p->ymaxheight = CARD_HEIGHT;
  257.     ++p;
  258.     }
  259.     p->x = p->y = -1;
  260.     return FREECELL_MAGIC;
  261. }
  262.  
  263.  
  264. static int gen_layout(int xnum, int ynum, int h) {
  265.     int i, cols, off, rows;
  266.     struct pile *p = graphic.pile;
  267.     int new_layout_type;
  268.  
  269.     /* try to do big layout */
  270.     graphic.preferred_height = YOFF;    /* will be increased */
  271.     cols = rules.numslots + rules.numdecks;
  272.     if (rules.variant & DECK_SOURCE)
  273.     ++cols;
  274.  
  275.     if (xnum >= cols && ynum >= 4) {
  276.     /* big layout is OK */
  277.     new_layout_type = 0;
  278.     cols -= rules.numdecks;
  279.     rows = 4;
  280.     if (xnum >= rules.numslots + rules.numdecks + 1) {
  281.         /* big layout with deck OK */
  282.         cols = rules.numslots + 1;
  283.         ++new_layout_type;
  284.     }
  285.     for (i = 0; i < rules.numstacks; ++i) {
  286.         p->x = graphic.xgap + (graphic.xgap + CARD_WIDTH) * (cols + i/4);
  287.         p->y = YOFF + SUIT(i) * (CARD_HEIGHT+graphic.ygap);
  288.         p->xtotal = CARD_WIDTH;
  289.         p->ymaxheight = CARD_HEIGHT;
  290.         ++p;
  291.     }
  292.     off = cols - rules.numslots;
  293.     for (i = 0; i < rules.numslots; ++i) {
  294.         p->x = graphic.xgap + (graphic.xgap + CARD_WIDTH) * (off+i);
  295.         p->y = YOFF;
  296.         p->xtotal = CARD_WIDTH;
  297.         p->ymaxheight = h - YOFF + BOTTOM_INC;
  298.         ++p;
  299.     }
  300.     cols += rules.numdecks;
  301.     } else {
  302.     /* small layout */
  303.     rows = 1 + SLOTFACTOR;
  304.     if (rules.numstacks > rules.numslots) {
  305.         new_layout_type = 2;
  306.         cols = rules.numstacks;
  307.     } else if (rules.numstacks == rules.numslots) {
  308.         if (rules.variant & DECK_SOURCE) {
  309.         new_layout_type = 5;
  310.         cols = rules.numstacks + 1;
  311.         } else {
  312.         new_layout_type = 4;    /* only case without a deck */
  313.         cols = rules.numstacks;
  314.         if (xnum >= cols + 1) {    /* have a deck anyway */
  315.             ++cols;
  316.             ++new_layout_type;    
  317.         }
  318.         }
  319.     } else {
  320.         new_layout_type = 6;
  321.         if (rules.variant & DECK_SOURCE)
  322.         cols = max(rules.numstacks + 2, rules.numslots);
  323.         else
  324.         cols = rules.numslots;
  325.     }
  326.  
  327.     off = cols - rules.numstacks;
  328.     for (i = 0; i < rules.numstacks; ++i) {
  329.         p->x = graphic.xgap + (graphic.xgap + CARD_WIDTH) * (i+off);
  330.         p->y = YOFF;
  331.         p->xtotal = CARD_WIDTH;
  332.         p->ymaxheight = CARD_HEIGHT;
  333.         ++p;
  334.     }
  335.     off = cols - rules.numslots;
  336.     for (i = 0; i < rules.numslots; ++i) {
  337.         p->x = graphic.xgap + (graphic.xgap + CARD_WIDTH) * (i+off);
  338.         p->y = YOFF + graphic.ygap + CARD_HEIGHT;
  339.         p->xtotal = CARD_WIDTH;
  340.         p->ymaxheight = h - YOFF - CARD_HEIGHT - graphic.ygap + BOTTOM_INC;
  341.         ++p;
  342.     }
  343.     }
  344.     /* fine. now do the deck(s) (if any) */
  345.     /* p is pointer to first deck pile */
  346.     /* cols is the number of columns on the tableau */
  347.     graphic.preferred_width = (cols+1) * graphic.xgap + cols * CARD_WIDTH;
  348.     graphic.preferred_height += rows * (graphic.ygap + CARD_HEIGHT);
  349. #ifdef LABER
  350.     printf("gen_layout setting up: %d rows, %d cols, preferred size = (%d,%d)\n",
  351.        rows, cols, graphic.preferred_width, graphic.preferred_height);
  352. #endif
  353.     p->xtotal = CARD_WIDTH;
  354.     p->ymaxheight = CARD_HEIGHT;
  355.     if (rules.variant & NODEAL) {
  356.     p->x = p->y = -1;
  357.     } else {
  358.     switch (new_layout_type) {
  359.     case 2: /* case 3: */
  360.         p->x = graphic.xgap;
  361.         p->y = YOFF + graphic.ygap + CARD_HEIGHT;
  362.         break;
  363.     case 0:    case 4:
  364.         p->x = p->y = -1;    /* no deck */
  365.         break;
  366.     case 1: case 5:
  367.         p->x = graphic.xgap;
  368.         p->y = YOFF + (graphic.ygap + CARD_HEIGHT) / 2;
  369.         break;
  370.     case 6: /* case 7: */
  371.         p->x = graphic.xgap;
  372.         p->y = YOFF;
  373.         break;
  374.     default:
  375.         abort();
  376.     }
  377.     }
  378.     /* do a second deck? */
  379.     if (rules.variant & DECK_SOURCE) {
  380.     p[1] = p[0];    /* IDECK is one more back */
  381.     if (new_layout_type == 6) {
  382.         p->y = YOFF;
  383.         p->x = 2 * graphic.xgap + CARD_WIDTH;
  384.     } else {
  385.         p->x = graphic.xgap;
  386.         p->y = YOFF + ((rules.variant & NODEAL) ? 1 : 3)
  387.         * (graphic.ygap + CARD_HEIGHT) / 2;
  388.     }
  389.     }
  390.     return new_layout_type;
  391. }
  392.  
  393. static int Delight_Layout(int xnum, int ynum, int h) {
  394.     int i, x = 0;
  395.     struct pile *p = graphic.pile;
  396.  
  397.     for (i = 0; i < game.numpiles; ++i) {
  398.     p = graphic.pile+i;
  399.     p->x = -1;
  400.     p->y = -1;
  401.     }
  402.     p = graphic.pile+IDECK;
  403.     p->x = (x += graphic.xgap);
  404.     p->y = YOFF;
  405.     p->xtotal = CARD_WIDTH;
  406.     p->ymaxheight = CARD_HEIGHT;
  407.  
  408.     /* want dest. for hint arrows */
  409.     p = graphic.pile+FIRST_STACK;
  410.     p->x = x;
  411.     p->y = YOFF + CARD_HEIGHT + graphic.ygap;
  412.     p->xtotal = CARD_WIDTH;
  413.     p->ymaxheight = CARD_HEIGHT;
  414.  
  415.     p = graphic.pile+FIRST_SLOT;
  416.     for (i = 0; i < rules.numslots; ++i) {
  417.     x += CARD_WIDTH + graphic.xgap;
  418.     p->x = x;
  419.     p->y = YOFF;
  420.     p->xtotal = CARD_WIDTH;
  421.     p->ymaxheight = h - YOFF + BOTTOM_INC;
  422.     ++p;
  423.     }
  424.     return DELIGHT_MAGIC;
  425. }
  426.  
  427. static int MonteCarlo_Layout(int xnum, int ynum, int h) {
  428.     int i, y, x;
  429.     struct pile *p = graphic.pile;
  430.  
  431.     for (i = 0; i < game.numpiles; ++i) {
  432.     p = graphic.pile+i;
  433.     p->x = -1;
  434.     p->y = -1;
  435.     }
  436.     y = YOFF;
  437.     p = graphic.pile+IDECK;
  438.     p->x = graphic.xgap;
  439.     p->y = y;
  440.     p->xtotal = CARD_WIDTH;
  441.     p->ymaxheight = CARD_HEIGHT;
  442.  
  443.     p = graphic.pile+FIRST_SLOT;
  444.     x = CARD_WIDTH + 2 * graphic.xgap;
  445.     for (i = 0; i < rules.numslots; ++i) {
  446.     p->x = x + (i%5) * (CARD_WIDTH + graphic.xgap + MCDX);
  447.     p->y = y + (i/5) * (CARD_HEIGHT + graphic.ygap + MCDY);
  448.     p->xtotal = CARD_WIDTH;
  449.     p->xdelta = MCDX;
  450.     p->delta = MCDY;
  451.     p->ymaxheight = CARD_HEIGHT + MCDY;
  452.     p->xmaxwidth = CARD_WIDTH + MCDX;
  453.     ++p;
  454.     }
  455.     return MONTECARLO_MAGIC;
  456. }
  457.  
  458. static int MidnightOil_Layout(int xnum, int ynum, int h) {
  459.     int i, y, x;
  460.     struct pile *p = graphic.pile;
  461.  
  462.     for (i = 0; i < game.numpiles; ++i) {
  463.     p = graphic.pile+i;
  464.     p->x = -1;
  465.     p->y = -1;
  466.     }
  467.  
  468.  
  469.     y = YOFF;
  470.     x = graphic.xgap;
  471.  
  472.  
  473.     p = graphic.pile+FIRST_SLOT;
  474.     for (i = 0; i < rules.numslots; ++i) {
  475.     p->x = x;
  476.     p->y = y;
  477.     p->xtotal = CARD_WIDTH;
  478.     p->ymaxheight = 2 * CARD_HEIGHT + graphic.ygap;
  479.     if (i & 1) {
  480.         p->y += p->ymaxheight + graphic.ygap;
  481.         x += CARD_WIDTH + graphic.xgap;
  482.     }
  483.     ++p;
  484.     }
  485.     if (rules.numslots & 1)
  486.     /* correctly advance x position */
  487.     x += graphic.xgap + CARD_WIDTH;
  488.  
  489.     p = graphic.pile+FIRST_STACK;
  490.     for (i = 0; i < rules.numstacks; ++i) {
  491.     p->x = x;
  492.     p->y = y + (i & 3) * (graphic.ygap + CARD_HEIGHT);
  493.     p->xtotal = CARD_WIDTH;
  494.     p->ymaxheight = CARD_HEIGHT;
  495.     if ((i&3) == 3)
  496.         x += CARD_WIDTH + graphic.xgap;
  497.     ++p;
  498.     }
  499.     return MIDNIGHTOIL_MAGIC;
  500. }
  501.  
  502. static int Michaels_Layout(int xnum, int ynum, int h) {
  503.     int i, j, y, x = graphic.xgap;
  504.     struct pile *p = graphic.pile;
  505.  
  506.     for (i = 0; i < game.numpiles; ++i) {
  507.     p = graphic.pile+i;
  508.     p->x = -1;
  509.     p->y = -1;
  510.     }
  511.     y = YOFF;
  512.     /* first the slots */
  513.     for (i = FIRST_SLOT; i <= LAST_SLOT; ++i) {
  514.     if (i == FIRST_SLOT+rules.numslots/2)
  515.         x += 5 * graphic.xgap + 3 * CARD_WIDTH;
  516.     p = graphic.pile+i;
  517.     p->x = x;
  518.     p->y = y;
  519.     x += graphic.xgap + CARD_WIDTH;
  520.     p->xtotal = CARD_WIDTH;
  521.     p->ymaxheight = h - YOFF + BOTTOM_INC;
  522.     }
  523.     /* now the tmps */
  524.     x = 2 * graphic.xgap + rules.numslots/2 * (CARD_WIDTH + graphic.xgap);
  525.     for (j = 0; j < rules.numtmps; ++j) {
  526.     p = graphic.pile+i+j;
  527.     p->x = x + ((j & 2) ? 2 * (graphic.xgap + CARD_WIDTH) : 0);
  528.     p->y = y + ((j & 1) ? 2 * (graphic.ygap + CARD_HEIGHT) : 0);
  529.     p->xtotal = CARD_WIDTH;
  530.     p->ymaxheight = CARD_HEIGHT;
  531.     }
  532.     /* at last the stacks */
  533.     for (i = FIRST_STACK; i <= LAST_STACK; ++i) {
  534.     static int xoff[] = { 0, 1, 1, 2 };
  535.     static int yoff[] = { 2, 1, 3, 2 };
  536.     p = graphic.pile+i;
  537.     p->x = x + xoff[i] * (CARD_WIDTH + graphic.xgap);
  538.     p->y = y + (yoff[i] * (CARD_HEIGHT + graphic.ygap)) / 2;
  539.     p->xtotal = CARD_WIDTH;
  540.     p->ymaxheight = CARD_HEIGHT;
  541.     }
  542.     return MICHAELS_MAGIC;
  543. }
  544.  
  545. static int Royal_Layout(int xnum, int ynum, int h) {
  546.     int i, x = graphic.xgap;
  547.     struct pile *p = graphic.pile;
  548.  
  549.     if (rules.numslots > 2)
  550.     x += (rules.numslots - 2) * (CARD_WIDTH+graphic.xgap) / 2;
  551.     p = graphic.pile + IDECK;
  552.     p->x = x;
  553.     p->y = YOFF;
  554.     --p;    /* VDECK */
  555.     p->x = x + graphic.xgap + CARD_WIDTH;
  556.     p->y = YOFF;
  557.     x = graphic.xgap;
  558.     for (i = FIRST_SLOT; i <= LAST_SLOT; ++i) {
  559.     p = graphic.pile+i;
  560.     p->x = x;
  561.     p->y = YOFF + CARD_HEIGHT + graphic.ygap;
  562.     x += graphic.xgap + CARD_WIDTH;
  563.     p->ymaxheight = 3 * CARD_HEIGHT + 2 * graphic.ygap;
  564.     }
  565.     x = 2 * graphic.xgap + max(rules.numslots, 2) * (CARD_WIDTH + graphic.xgap);
  566.     for (i = FIRST_STACK; i <= LAST_STACK; ++i) {
  567.     p = graphic.pile+i;
  568.     p->x = x + (i / 4) * (CARD_WIDTH + graphic.xgap);
  569.     p->y = YOFF + (i & 3) * (CARD_HEIGHT + graphic.ygap);
  570.     }
  571.     x += rules.numdecks * (graphic.xgap + CARD_WIDTH) + graphic.xgap;
  572.     for (i = 0; i < rules.numtmps; ++i) {
  573.     p = graphic.pile+LAST_SLOT+1+i;
  574.     p->x = x + (i / 4) * (CARD_WIDTH + graphic.xgap);
  575.     p->y = YOFF + (i & 3) * (CARD_HEIGHT + graphic.ygap);
  576.     }
  577.     return ROYAL_MAGIC;
  578. }
  579.  
  580. static int Bakers_Layout(int xnum, int ynum, int h) {
  581.     int i, x;
  582.     struct pile *p;
  583.  
  584.     for (i = FIRST_SLOT; i <= LAST_SLOT; ++i) {
  585.     p = graphic.pile+i;
  586.     p->x = graphic.xgap + (i - FIRST_SLOT) / 2 * (CARD_WIDTH + graphic.xgap);
  587.     p->y = YOFF + ((i - FIRST_SLOT) % 2) * 2 * (CARD_HEIGHT + graphic.ygap);
  588.     p->ymaxheight = 2 * CARD_HEIGHT + graphic.ygap;
  589.     }
  590.  
  591.     x = graphic.xgap + (rules.numslots+1)/2 * (CARD_WIDTH + graphic.xgap);
  592.     for (i = FIRST_STACK; i <= LAST_STACK; ++i) {
  593.     p = graphic.pile+i;
  594.     p->x = x + (i / 4) * (CARD_WIDTH + graphic.xgap);
  595.     p->y = YOFF + (i & 3) * (CARD_HEIGHT + graphic.ygap);
  596.     }
  597.     return BAKERS_MAGIC;
  598. }
  599.  
  600. static int Canfield_Layout(int xnum, int ynum, int h) {
  601.     int i;
  602.     struct pile *p;
  603.  
  604.     for (i = FIRST_SLOT; i <= LAST_SLOT; ++i) {
  605.     p = graphic.pile+i;
  606.     p->x = graphic.xgap + (i - FIRST_SLOT+1) * (CARD_WIDTH + graphic.xgap);
  607.     p->y = YOFF + (CARD_HEIGHT + graphic.ygap);
  608.     p->ymaxheight = 3 * CARD_HEIGHT + graphic.ygap;
  609.     }
  610.     for (i = FIRST_STACK; i <= LAST_STACK; ++i) {
  611.     p = graphic.pile+i;
  612.     p->x = graphic.xgap + (i+1) * (CARD_WIDTH + graphic.xgap);
  613.     p->y = YOFF;
  614.     }
  615.     p = graphic.pile + LAST_SLOT + 1;
  616.     /* the stock */
  617.     p->x = graphic.xgap;
  618.     p->y = YOFF + (CARD_HEIGHT + graphic.ygap)/2;
  619.     
  620.     ++p;
  621.     /* the talon */
  622.     p->x = graphic.xgap;
  623.     p->y = p[-1].y + (CARD_HEIGHT + graphic.ygap);
  624.  
  625.     ++p;
  626.     /* the hand */
  627.     p->x = graphic.xgap;
  628.     p->y = p[-1].y + (CARD_HEIGHT + graphic.ygap);
  629.     return CANFIELD_MAGIC;
  630. }
  631.  
  632. void init_layout(void) {
  633.     int w, h;
  634.     static int layout_type = -1, yoff = -1;
  635.     static long magic = -1;
  636.     int new_layout_type;
  637.     long new_magic = 0;
  638.     int xnum, ynum;    /* number of cards in either direction */
  639.  
  640.     /* get the size of the actual window */
  641. #ifdef useXaw
  642.     w = graphic.w_width;
  643.     h = graphic.w_height;
  644. #else
  645.     w = graphic.width;
  646.     h = graphic.height;
  647. #endif
  648. #ifdef LABER
  649.     printf("init_layout requested for size (%d,%d)\n", w, h);
  650. #endif
  651.  
  652. #ifdef useXlib
  653.     {   int x, y;
  654.     x = graphic.xgap;
  655.     y = graphic.ygap;
  656.     /* y is used space in vertical direction */
  657.     /* get new_magic! */
  658.     button.num = arrange_buttons(button.b, &x, &y, w, &new_magic);
  659.     /* sorry, work is done twice */
  660.     graphic.yoff = calc_yoff(w);
  661.     }
  662. #endif
  663.  
  664.     xnum = (w - graphic.xgap) / (CARD_WIDTH+graphic.xgap);
  665.     ynum = (h - YOFF) / (CARD_HEIGHT+graphic.ygap);
  666.  
  667.     /* the default is that there is only one layout per rule set,
  668.        which is minsize and preferred size at the same time.
  669.        So we set it here. It can be overridden by the special
  670.        layout functions */
  671.     graphic.preferred_width = graphic.min_width;
  672.     graphic.preferred_height = graphic.min_height;
  673.  
  674.     /* assign defaults */
  675.     {   Pileindex i;
  676.     struct pile *p;
  677.     for (i = 0; i < game.numpiles; ++i) {
  678.         p = graphic.pile+i;
  679.         p->x = -1;
  680.         p->y = -1;
  681.         p->xtotal = CARD_WIDTH;
  682.         p->ytotal = CARD_HEIGHT;
  683.         p->xmaxwidth  = CARD_WIDTH;
  684.         p->ymaxheight = CARD_HEIGHT;
  685.         p->xdelta  = 0;
  686.     }
  687.     }
  688.     switch (rules.layout_hints) {
  689.     case 0:
  690.     case 1:
  691.     new_layout_type = rules.numtmps ?
  692.         FreeCell_layout(xnum, ynum, h) :
  693.         gen_layout(xnum, ynum, h);
  694.     break;
  695.     case 2:
  696.     new_layout_type = Delight_Layout(xnum, ynum, h);
  697.     break;
  698.     case 3:
  699.     new_layout_type = MonteCarlo_Layout(xnum, ynum, h);
  700.     break;
  701.     case 4:
  702.     new_layout_type = MidnightOil_Layout(xnum, ynum, h);
  703.     break;
  704.     case 5:
  705.     new_layout_type = Michaels_Layout(xnum, ynum, h);
  706.     break;
  707.     case 6:
  708.     new_layout_type = Royal_Layout(xnum, ynum, h);
  709.     break;
  710.     case 7:
  711.     new_layout_type = Bakers_Layout(xnum, ynum, h);
  712.     break;
  713.     case 8:
  714.     new_layout_type = Canfield_Layout(xnum, ynum, h);
  715.     break;
  716.     default:
  717.     new_layout_type = 0xffff;    /* keep compiler happy */
  718.     assert(0);
  719.     }
  720.     /* printf("deck %d position: (%d,%d), first slot at (%d,%d)\n",
  721.     p - graphic.pile, p->x, p->y,
  722.     graphic.pile[rules.numstacks].x, graphic.pile[rules.numstacks].y);
  723.     printf("cols = %d, off = %d\n", cols, off);
  724.     printf("xxdeck at pos %d,%d\n", graphic.pile[DECK].x, graphic.pile[DECK].y); */
  725.     if (new_layout_type != layout_type || YOFF != yoff) {    /* everything changed */
  726.     layout_type = new_layout_type;
  727.     yoff = YOFF;
  728.     magic = new_magic;
  729.     refresh_screen();
  730.     } else if (magic != new_magic) {        /* at least one button did move */
  731.     magic = new_magic;
  732.     XClearArea(dpy, table, 0, 0, 0, YOFF-2, True);    /* just redraw the buttons */
  733.     }
  734. }
  735.  
  736. int pile_resize(int i) {
  737.     int j, delta, xdelta;
  738.     struct pile *p;
  739.  
  740.     p = graphic.pile + i;
  741.     p->xtotal = CARD_WIDTH;
  742.     p->ytotal = CARD_HEIGHT;
  743.     if (game.piletype[i] == Slot)
  744.     delta = STD_DELTA;
  745.     else
  746.     delta = 0;
  747.     xdelta = 0;
  748.     if (game.piletype[i] != Slot || EMPTY(i)) {
  749.     /* done */
  750.     /* p->xdelta = xdelta; */
  751.     p->delta = delta;
  752.     return 0;
  753.     }
  754.  
  755.     if (CARDS_ON_PILE(i) > 1)
  756.     delta = (p->ymaxheight-CARD_HEIGHT) / (CARDS_ON_PILE(i)-1);
  757.  
  758.     if (delta > STD_DELTA)          /* respect maximum value */
  759.     delta = STD_DELTA;
  760.     if (delta < 1)                  /* respect minimum value */
  761.         delta = 1;
  762.  
  763.     /* printf("delta = %d, %d cards on pile %d\n", delta, CARDS_ON_PILE(i), i); */
  764.     j = INDEX_OF_FIRST_CARD(i);
  765.     graphic.cardy[j] = 0;
  766.     while (j != INDEX_OF_LAST_CARD(i)) {    /* not topmost card */
  767.     p->ytotal += delta;
  768.     graphic.cardy[j+1] = graphic.cardy[j] + delta;
  769.     ++j;
  770.     }
  771.     j = graphic.pile[i].delta != delta;    /* change of shrink factor? */
  772.     graphic.pile[i].delta = delta;
  773.     /* graphic.pile[i].xdelta = xdelta; */    /* unchanged for now */
  774.     return j;
  775. }
  776.